import java.util.ArrayList;
import java.util.Random;

public abstract class MonsterStrategy {
	protected Map map;
	protected Monster monster;
	
	public MonsterStrategy(Map map, Monster monster){
		this.map = map;
		this.monster = monster;
	}
	
	public void step() {
		if (monster.getX() % Entity.getEntityWidth() == 0
			&& monster.getY() % Entity.getEntityHeight() == 0) {
			
			ArrayList<Integer> places = findAvailablePlaces();
			
			determineNextDirection(places);
		}
		
		move();
	}
	
	private ArrayList<Integer> findAvailablePlaces() {
		int indexY = monster.getY() / Entity.getEntityHeight();
		int indexX = monster.getX() / Entity.getEntityWidth();
		
		ArrayList<Integer> places = new ArrayList<Integer>();
		
		if(map.isIndexMoveable(indexX + 1, indexY)){
			places.add(Monster.RIGHT);
		}
		if(map.isIndexMoveable(indexX -1, indexY)){
			places.add(Monster.LEFT);			
		}
		if(map.isIndexMoveable(indexX, indexY +1)){
			places.add(Monster.DOWN);
		}
		if(map.isIndexMoveable(indexX, indexY - 1)){
			places.add(Monster.UP);
		}
		
		return places;
	}
	
	// Let derived classes determine the next direction
	protected abstract void determineNextDirection(ArrayList<Integer> places);

	private void move() {
		if (monster.getDirection() == Monster.NOMOVE) {
			return;
		}
		
		if (monster.getDirection() == Monster.UP) {
			monster.setY(monster.getY() - monster.getStepY());
		} else if (monster.getDirection() == Monster.DOWN) {
			monster.setY(monster.getY() + monster.getStepY());
		} else if (monster.getDirection() == Monster.LEFT) {
			monster.setX(monster.getX() - monster.getStepX());
		} else if (monster.getDirection() == Monster.RIGHT) {
			monster.setX(monster.getX() + monster.getStepX());
		}
	}
	
	protected void moveRandom(ArrayList<Integer> places) {
		Random random = new Random();
		
		float r = random.nextFloat();
		
		for (int i = 1; i <= places.size(); i++) {
			if (r < (float)i/places.size()  && (float)(i-1)/places.size() < r) {
				monster.setDirection(places.get(i-1));
			}
		}
	}
}
